]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
shell-screenshot: Apply monitor scale to cursor surface
authorMarco Trevisan (Treviño) <mail@3v1n0.net>
Wed, 13 Feb 2019 01:30:28 +0000 (02:30 +0100)
committerJonas Ådahl <jadahl@gmail.com>
Fri, 1 Mar 2019 17:12:53 +0000 (17:12 +0000)
When we grab a screenshot of a framebuffer scaled shell, we shoudl apply the
device scale to the image surface, while the monitor scaling should be applied
to the cursor surface, so that it's painted at proper coordinates and in proper
size in the generated image.

This is not needed for XWayland clients as they are not scaled anyways, while
for wayland clients that are painted in multiple monitors, this might cause
a lower quality cursor in the lower dpi monitor, because the cursor sprite is
generated for the monitor scale, and not for the surface scale.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/5

src/shell-screenshot.c

index 00c8cd227b28235ab270ce1bc0bb93bbeca2a843..61fdc1d1eeb0b07bfcbd2f12df05237b2c53b7d1 100644 (file)
@@ -323,6 +323,22 @@ draw_cursor_image (cairo_surface_t       *surface,
                                                         width, height,
                                                         stride);
 
+  cairo_surface_get_device_scale (surface, &xscale, &yscale);
+
+  if (xscale != 1.0 || yscale != 1.0)
+    {
+      int monitor;
+      float monitor_scale;
+      MetaRectangle cursor_rect = {
+        .x = x, .y = y, .width = width, .height = height
+      };
+
+      monitor = meta_display_get_monitor_index_for_rect (display, &cursor_rect);
+      monitor_scale = meta_display_get_monitor_scale (display, monitor);
+
+      cairo_surface_set_device_scale (cursor_surface, monitor_scale, monitor_scale);
+    }
+
   cr = cairo_create (surface);
   cairo_set_source_surface (cr,
                             cursor_surface,
@@ -462,7 +478,18 @@ grab_window_screenshot (ClutterActor *stage,
   priv->datetime = g_date_time_new_now_local ();
 
   if (priv->include_cursor)
-    draw_cursor_image (priv->image, priv->screenshot_area);
+    {
+      if (meta_window_get_client_type (window) == META_WINDOW_CLIENT_TYPE_WAYLAND)
+        {
+          float resource_scale;
+          if (!clutter_actor_get_resource_scale (window_actor, &resource_scale))
+            resource_scale = 1.0f;
+
+          cairo_surface_set_device_scale (priv->image, resource_scale, resource_scale);
+        }
+
+      draw_cursor_image (priv->image, priv->screenshot_area);
+    }
 
   g_signal_handlers_disconnect_by_func (stage, grab_window_screenshot, result);
   task = g_task_new (screenshot, NULL, on_screenshot_written, result);